﻿using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using NHibernate;

namespace DAL
{
    delegate Object hibernateTransactionDelegate(executeHibernateDelegate execute, ISession session, String methodOrHql, params Object[] parameters);
    delegate Object executeHibernateDelegate(ISession session, String methodOrHql, params Object[] parameters);

    class DALProxy
    {
        public static Object doHibernateProxy(ISession session, String methodName, params Object[] parameters)
        {
            return new hibernateTransactionDelegate(DALProxy.hibernateTransactionProxy)(new executeHibernateDelegate(DALProxy.doHibernate), session, methodName, parameters);
        }

        public static IList doExecuteHql(ISession session, string hql, params Object[] parameters)
        {
            return (IList)new hibernateTransactionDelegate(DALProxy.hibernateTransactionProxy)(new executeHibernateDelegate(DALProxy.executeHql), session, hql, parameters);
        }

        public static int doUpdateHql(ISession session, string hql, params Object[] parameters)
        {
            return (int)new hibernateTransactionDelegate(DALProxy.hibernateTransactionProxy)(new executeHibernateDelegate(DALProxy.executeUpdateHql), session, hql, parameters);
        }

        public static DataTable doExecuteSql(String connString, String sql, params Object[] parameters)
        {
            SqlConnection connection = new SqlConnection(connString);
            try
            {
                connection.Open();
            }
            catch
            {
                Console.WriteLine("数据库连接失败");
                return null;
            }
            SqlDataAdapter dataAdapter = new SqlDataAdapter();
            SqlCommand command = new SqlCommand(sql, connection);
            for (int i = 0; i != parameters.Length; ++i)
            {
                command.Parameters.AddWithValue("@" + i, parameters[i]);
            }
            dataAdapter.SelectCommand = command;
            DataTable dataTable = new DataTable();
            try
            {
                dataAdapter.Fill(dataTable);
            }
            catch
            {
                Console.WriteLine("Sql查询失败");
            }
            finally
            {
                try
                {
                    connection.Close();
                }
                catch
                {
                    Console.WriteLine("数据库关闭失败");
                }
            }
            return dataTable;
        }

        private static Object hibernateTransactionProxy(executeHibernateDelegate execute, ISession session, String methodOrHql, params Object[] parameters)
        {
            Object result = null;
            ITransaction transaction = null;
            try
            {
                transaction = session.BeginTransaction();
                result = execute(session, methodOrHql, parameters);
                transaction.Commit();
            }
            catch
            {
                Console.WriteLine("Hibernate操作失败");
                if (session == null)
                {
                    return null;
                }
                try
                {
                    transaction.Rollback();
                }
                catch
                {
                    Console.WriteLine("事物回滚失败");
                }
            }
            finally
            {
                try
                {
                    session.Close();
                }
                catch
                {
                    Console.WriteLine("数据库关闭失败");
                }
            }
            return result;
        }

        private static Object doHibernate(ISession session, String methodName, params Object[] parameters)
        {
            return session.GetType().GetMethod(methodName, getTypes(parameters)).Invoke(session, parameters);
        }

        private static IList executeHql(ISession session, string hql, params Object[] parameters)
        {
            IQuery query = session.CreateQuery(hql);
            for (int i = 0; i != parameters.Length; ++i)
            {
                query.SetParameter(i, parameters[i]);
            }
            return query.List();
        }

        private static Object executeUpdateHql(ISession session, string hql, params Object[] parameters)
        {
            //String thisHql = "update Borrow bo set bo.renewCount=(select buffer.renewCount + 1 from Borrow buffer where buffer.id=bo.id), bo.shouldReturnDate=? where bo.renewCount<(select buffer.user.userType.enableRenewCount from Borrow buffer where buffer.id=bo.id) and bo.shouldReturnDate>=current_date() and bo.user.id=?";
            IQuery query = session.CreateQuery(hql);
            for (int i = 0; i != parameters.Length; ++i)
            {
                query.SetParameter(i, parameters[i]);
            }
            return query.ExecuteUpdate();
        }

        private static Type[] getTypes(Object[] parameters)
        {
            Type[] types = new Type[parameters.Length];
            for (int i = 0; i != parameters.Length; ++i)
            {
                types[i] = parameters[i].GetType();
            }
            return types;
        }
    }
}
